package com.example.springflowable.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.springflowable.ask_for_leave.service.impl.AskLeaveTaskServiceImpl;
import com.example.springflowable.common.Results;
import com.example.springflowable.model.TaskModel;
import com.example.springflowable.service.TaskCommonService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import io.swagger.annotations.ApiParam;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.*;
import org.flowable.engine.form.StartFormData;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.runtime.ProcessInstanceBuilder;
import org.flowable.form.api.FormInfo;
import org.flowable.form.api.FormRepositoryService;
import org.flowable.form.model.FormField;
import org.flowable.form.model.SimpleFormModel;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.awt.geom.RectangularShape;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Classname ProcessController
 * @Description TODO
 * @Date 2022/5/9 11:03
 * @Created by XiongXiong
 * @Author: X.I.O
 */
@Api(tags = "流程服务")
@RestController
@RequestMapping(value = "process")
public class ProcessController {

    Logger logger= LoggerFactory.getLogger(ProcessController.class);

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskCommonService taskCommonService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private FormRepositoryService formRepositoryService;

    @Autowired
    private FormService formService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private ProcessEngine processEngine;

//    @ApiOperation("获取所有流程模型")
//    @GetMapping("getallprocess")
//    public JSONObject getProcessController(){
//        List<Deployment> list = repositoryService.createDeploymentQuery().list();
//        JSONArray array = new JSONArray();
//        for (Deployment deployment : list) {
//            JSONObject obj=new JSONObject();
//            obj.put("id",deployment.getId());
//            obj.put("name",deployment.getName());
//            obj.put("key",deployment.getKey());
//            array.add(obj);
//        }
//        return Results.success(array);
//    }

    @ApiOperation("流程列表")
    @PostMapping("keylist")
    public JSONObject  processFileController(){
        File file = null;
        try {
            file = ResourceUtils.getFile("classpath:processes");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if(file==null){
            return Results.success();
        }
        File[] files=file.listFiles();
        JSONArray jsonArray = new JSONArray();
        JSONObject obj=null;
        for (int i = 0; i <files.length ; i++) {
            File f = files[i];
            obj = new JSONObject();
            obj.put("name",f.getName().replace(".bpmn20.xml",""));
            jsonArray.add(obj);
        }
        return Results.success(jsonArray);
    }

    @ApiOperation("流程创建")
    @PostMapping("createProcess")
    public JSONObject createProcessController(@ApiParam("流程key")@RequestParam("processKey")String processKey,
                                              @ApiParam("流程标题")@RequestParam("processTitle")String processTitle,
                                              @ApiParam("流程用户id")@RequestParam("uid")String uid
    ){
        logger.info("流程开始创建了===============>");
        Authentication.setAuthenticatedUserId(uid);
        HashMap<String, Object> map = new HashMap<>();
        map.put("uid", uid);
        ProcessInstanceBuilder processInstanceBuilder=runtimeService.createProcessInstanceBuilder();
      //  processInstanceBuilder.businessKey("123456789");
        processInstanceBuilder.processDefinitionKey(processKey);
        processInstanceBuilder.name(processTitle);
        processInstanceBuilder.variables(map);
        ProcessInstance processInstance=processInstanceBuilder.start();
        Authentication.setAuthenticatedUserId(null);
        logger.info("创建请假流程 processId：{}", processInstance.getId());
        return Results.success(processInstance.getId());
    }

    @ApiOperation("获取用户的待办")
    @PostMapping("getdealwith")
    public JSONObject getDealWithController(@RequestParam("uid")String uid,
                                            @RequestParam(value = "pageNum",defaultValue = "1")Integer pageNum,
                                            @RequestParam(value = "pageSize",defaultValue = "10")Integer pageSize){
       List<TaskModel> taskModels=taskCommonService.getMyTaskList(uid,pageNum,pageSize);
       return Results.success(taskModels);
    }

    @ApiOperation("获取用户的已办")
    @PostMapping("getdealedwith")
    public JSONObject getDealedwithController(@RequestParam("uid")String uid,
                                              @RequestParam(value = "pageNum",defaultValue = "0")Integer pageNum,
                                              @RequestParam(value = "pageSize",defaultValue = "10")Integer pageSize){
        List<TaskModel> taskModels=taskCommonService.getMyHistoryTaskList(uid, pageNum, pageSize);
        return Results.success(taskModels);
    }

    @ApiOperation("获取流程的表单")
    @GetMapping("getprocessform")
    public JSONObject getProcessFrom(@RequestParam("processInstId")String processInstanceId){
        ProcessInstance processInstance=runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        String processDefinitionKey=null;
        if(processInstance==null){
            HistoricProcessInstance historicProcessInstance=historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            processDefinitionKey=historicProcessInstance.getProcessDefinitionKey();
        }else {
            processDefinitionKey = processInstance.getProcessDefinitionKey();
        }
        System.out.println(processDefinitionKey);
        ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefinitionKey).latestVersion().singleResult();
        StartFormData form = formService.getStartFormData(pd.getId());
        FormInfo info = formRepositoryService.getFormModelByKey(form.getFormKey());

        SimpleFormModel sfm = (SimpleFormModel) info.getFormModel();

        List<FormField> fields = sfm.getFields();
        for (FormField ff : fields) {
            System.out.println();
            System.out.println("id: " + ff.getId());
            System.out.println("name: " + ff.getName());
            System.out.println("type: " + ff.getType());
            System.out.println("placeholder: " + ff.getPlaceholder());
            System.out.println("value: " + ff.getValue());
            System.out.println(JSONObject.toJSONString(ff.getParams()));
            System.out.println();
        }
        return Results.success();
    }

    @ApiOperation("通过流程id获取任务的历史节点")
    @PostMapping("gettaskhistorylist")
    public JSONObject getTaskHistoryListController(@RequestParam("processId")String processId){
        List<TaskModel> taskModels = taskCommonService.getHistoryTaskListByProcessInstanceId(processId);
        return Results.success(taskModels);
    }

    @ApiOperation("获取流程的任务信息")
    @PostMapping("gettaskbyprocess")
    public JSONObject getProcessTaskController(@RequestParam("processId")String processId){
        List<TaskModel> taskModels = taskCommonService.getTaskModelListByProcessInstanceId(processId);
        return Results.success(taskModels);
    }

    @ApiOperation("流程提交到下一节点")
    @PostMapping("submitnextnode")
    public JSONObject submitController(@RequestParam("processId")String processId,
                                       @RequestParam("uid")String uid,
                                       @RequestParam("msg")String msg,
                                       @RequestParam(value = "checkResult",required = false)String checkResult){
        Map<String,Object> map = new HashMap<>();
        map.put("uid",uid);
        map.put("checkResult",checkResult);
        taskCommonService.complete(processId,uid,msg,map);
        return Results.success("提交成功");
    }



    @ApiOperation("获取下一节点信息")
    @PostMapping("getnextNode")
    public JSONObject getNextNodeController(@ApiParam("流程id")@RequestParam("processId") String processId){

      //  Task task = processEngine().getTaskService().createTaskQuery().taskId(taskId).singleResult();
        List<Task> tasks=taskCommonService.getTaskListByProcessInstanceId(processId);
        if(tasks==null){
            return Results.error("任务信息为null");
        }
        Task task=tasks.get(0);
        ExecutionEntity ee = (ExecutionEntity) runtimeService.createExecutionQuery()
                .executionId(task.getExecutionId()).singleResult();
        // 当前审批节点
        String crruentActivityId = ee.getActivityId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(crruentActivityId);
        // 输出连线
        List<SequenceFlow> outFlows = flowNode.getOutgoingFlows();
        JSONArray array=new JSONArray();
        for (SequenceFlow seq : outFlows) {
            //当前审批节点
                FlowElement sourceFlowElement = seq.getSourceFlowElement();
                JSONObject obj=new JSONObject();
                obj.put("now","当前节点："+sourceFlowElement.getId() +" 节点名称： "+sourceFlowElement.getName());
                // 下一个审批节点
                FlowElement targetFlow = seq.getTargetFlowElement();
                if (targetFlow instanceof UserTask) {
                    obj.put("next","下一节点："+targetFlow.getId() +" 节点名称： "+targetFlow.getName());
                }
                // 如果下个审批节点为结束节点
                if (targetFlow instanceof EndEvent) {
                    obj.put("end","下一节点："+targetFlow.getId() +" 节点名称： "+targetFlow.getName());
                }
                if(targetFlow instanceof ExclusiveGateway){

                    taskCommonService.dealGetWay(targetFlow,new HashMap());

                    obj.put("getway","下一节点: "+targetFlow.getId() + "节点名称: "+targetFlow.getName()+" ");

                }
                array.add(obj);
        }
        return Results.success(array);
    }








    @ApiOperation("上传文件部署流程")
    @PostMapping("processdeploy")
    public JSONObject processDeployment(@RequestParam("file") MultipartFile file,
                                        @RequestParam("name")String name) throws IOException {
        if(file==null){
            return Results.error("上传文件不得为空");
        }
        String resourceName = file.getOriginalFilename();
        Deployment deployStream = repositoryService.createDeployment()
                .name(name)
                .addInputStream(resourceName, file.getInputStream())
                .deploy();
        return Results.success("部署成功");
    }

    @ApiOperation("resource流程部署")
    @PostMapping("resourceDeploy")
    public JSONObject resourceDeployController(){
        File file = null;
        try {
            file = ResourceUtils.getFile("classpath:processes");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if(file!=null){
            File[] files=file.listFiles();
            for (File f : files) {
                System.out.println(f.getName());
                Deployment deployClasspath = repositoryService.createDeployment()
                        .name(f.getName().replace(".bpmn20.xml",""))
                        .addClasspathResource("processes/"+f.getName())
                        .deploy();
            }
        }
        return Results.success();
    }


    @ApiOperation("查询流程历史节点信息")
    @PostMapping("runallnode")
    public JSONObject runAllNode(String processInstanceId){

        // 获得活动的节点
        List<HistoricActivityInstance> highLightedActivityList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).
                orderByHistoricActivityInstanceStartTime().asc().list();
        List<Map<String,String>> maps=new ArrayList<>();
        boolean flag=false;
        for (HistoricActivityInstance tempActivity : highLightedActivityList) {
            Map<String,String> map=new HashMap<>();
            String activityId = tempActivity.getActivityId();

            String name=tempActivity.getActivityName();
            String czr=tempActivity.getAssignee();
            String type=tempActivity.getActivityType();
            if("userTask".equals(type)){
                map.put("name",name);
                map.put("czr",czr);
            }
            if("exclusiveGateway".equals(type)){
                Map<String,String> nextMap=getLastMap(maps);
                nextMap.put("event",name);
                flag=true;
            }
            if("sequenceFlow".equals(type)){
                if(flag){
                    Map<String,String> nextMap=getLastMap(maps);
                    nextMap.put("eventResult",name);
                    flag=false;
                }
            }
            if("endEvent".equals(type)){
                map.put("end","isend");
            }
            if(!map.isEmpty()){
                maps.add(map);
            }
        }
        return Results.success(maps);
    }

    private Map<String,String> getLastMap( List<Map<String,String>> maps){
        if(maps == null || maps.isEmpty()){
            return new HashMap<>();
        }
        return maps.get(maps.size() - 1);
    }



    @ApiOperation("高亮显示流程图")
    @GetMapping(value = "diagram-view")
    public void diagramView(String processInstanceId, HttpServletResponse httpServletResponse) {
        // 获得当前活动的节点
        String processDefinitionId;
        // 如果流程已经结束，则得到结束节点
        if (this.isFinished(processInstanceId)) {
            HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            processDefinitionId = pi.getProcessDefinitionId();
        } else {
            // 如果流程没有结束，则取当前活动节点
            // 根据流程实例ID获得当前处于活动状态的ActivityId合集
            ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            processDefinitionId = pi.getProcessDefinitionId();
        }
        List<String> highLightedActivities = new ArrayList<>();

        // 获得活动的节点
        List<HistoricActivityInstance> highLightedActivityList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();

        List<String> highLightedFlows = new ArrayList<>();

        for (HistoricActivityInstance tempActivity : highLightedActivityList) {
            String activityId = tempActivity.getActivityId();
            highLightedActivities.add(activityId);
            if("sequenceFlow".equals(tempActivity.getActivityType())){
                highLightedFlows.add(tempActivity.getActivityId());
            }
        }

        // 获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        ProcessEngineConfiguration engConf = processEngine.getProcessEngineConfiguration();

        ProcessDiagramGenerator diagramGenerator = engConf.getProcessDiagramGenerator();
//		ProcessDiagramGenerator diagramGenerator = new CustomProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "bmp", highLightedActivities, highLightedFlows, engConf.getActivityFontName(),
                engConf.getLabelFontName(), engConf.getAnnotationFontName(), engConf.getClassLoader(), 1.0, true);
        OutputStream out = null;
        byte[] buf = new byte[1024];
        int length;
        try {
            out = httpServletResponse.getOutputStream();
            while ((length = in.read(buf)) != -1) {
                out.write(buf, 0, length);
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            if (out != null) {
                try {
                    out.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
            if(in != null){
                try {
                    in.close();
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private boolean isFinished(String processInstanceId){
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        return pi==null;
    }






//    @ApiOperation("获取所有流程模型")
//    public JSONObject getAllProcessModel(){
//
//    }
}
